/**
 * SmartUI Studio - 项目浏览器功能
 * 合并了面板折叠功能和测试用例/测试任务管理功能
 */

document.addEventListener('DOMContentLoaded', function() {
    // 初始化折叠面板
    initCollapsiblePanels();
    
    // 初始化测试用例和测试任务面板
    initTestPanels();
    
    // 设置添加按钮事件
    setupPanelButtons();
    
    // 初始化步骤选择器模态框事件
    initStepSelectorEvents();
    
    // 初始化设备选择器
    initDeviceSelector();
});

/**
 * 初始化步骤选择器模态框事件
 */
function initStepSelectorEvents() {
    // 步骤类型选择事件
    document.querySelectorAll('.step-type-item').forEach(item => {
        item.addEventListener('click', function() {
            const stepType = this.getAttribute('data-type');
            const position = document.getElementById('stepSelectorModal').getAttribute('data-insert-position');
            
            // 获取当前选中的测试用例ID
            const activeTestcase = document.querySelector('#project-testcases .file-item.active');
            if (!activeTestcase) return;
            const testcaseId = activeTestcase.getAttribute('data-id');
            
            // 关闭步骤选择器模态框
            const modal = bootstrap.Modal.getInstance(document.getElementById('stepSelectorModal'));
            modal.hide();
            
            // 打开步骤编辑模态框
            openStepEditModal(testcaseId, stepType, position);
        });
    });
}

/**
 * 打开步骤编辑模态框
 * @param {string} testcaseId - 测试用例ID
 * @param {string} stepType - 步骤类型
 * @param {string} position - 插入位置
 */
function openStepEditModal(testcaseId, stepType, position) {
    // 创建新步骤的默认数据
    const stepData = {
        id: 'new_' + Date.now(),
        type: stepType,
        title: getStepTypeTitle(stepType),
        params: {}
    };
    
    // 填充编辑表单
    document.getElementById('stepId').value = stepData.id;
    document.getElementById('stepType').value = stepData.type;
    document.getElementById('stepTitle').value = stepData.title;
    
    // 根据步骤类型动态生成参数表单
    generateStepParamsForm(stepData);
    
    // 显示编辑模态框
    const modal = new bootstrap.Modal(document.getElementById('stepEditModal'));
    modal.show();
    
    // 设置保存按钮事件
    document.getElementById('saveStepBtn').onclick = function() {
        createNewStep(testcaseId, position);
    };
}

/**
 * 获取步骤类型的标题
 * @param {string} stepType - 步骤类型
 * @returns {string} 步骤标题
 */
function getStepTypeTitle(stepType) {
    switch (stepType) {
        case 'startApp': return '启动应用';
        case 'click': return '点击元素';
        case 'input': return '输入文本';
        case 'wait': return '等待';
        case 'assertion': return '断言';
        case 'custom': return '自定义脚本';
        default: return stepType;
    }
}

/**
 * 创建新步骤
 * @param {string} testcaseId - 测试用例ID
 * @param {string} position - 插入位置
 */
function createNewStep(testcaseId, position) {
    // 获取表单数据
    const form = document.getElementById('stepEditForm');
    const formData = new FormData(form);
    const stepType = formData.get('stepType');
    const stepTitle = formData.get('stepTitle');
    
    // 构建参数对象
    const params = {};
    switch (stepType) {
        case 'startApp':
            params.appPackage = formData.get('appPackage');
            params.waitTime = formData.get('waitTime');
            break;
            
        case 'click':
            params.elementId = formData.get('elementId');
            params.waitTime = formData.get('waitTime');
            break;
            
        case 'input':
            params.elementId = formData.get('elementId');
            params.text = formData.get('text');
            break;
            
        case 'wait':
            params.waitTime = formData.get('waitTime');
            break;
            
        case 'assertion':
            params.elementId = formData.get('elementId');
            params.condition = formData.get('condition');
            break;
            
        case 'custom':
            params.scriptContent = formData.get('scriptContent');
            break;
    }
    
    // 构建步骤数据
    const stepData = {
        type: stepType,
        title: stepTitle,
        params: params
    };
    
    // 发送API请求创建步骤
    axios.post(`/api/teststeps?api=create_step`, {
        testcaseId: testcaseId,
        stepData: stepData,
        position: position
    })
    .then(response => {
        // 关闭模态框
        const modal = bootstrap.Modal.getInstance(document.getElementById('stepEditModal'));
        modal.hide();
        
        // 重新加载测试步骤
        loadTestcaseSteps(testcaseId);
        
        // 显示成功通知
        showNotification('success', '步骤创建成功');
    })
    .catch(error => {
        console.error('创建步骤出错:', error);
        showNotification('error', `创建步骤失败: ${error.message}`);
    });
}

/**
 * 初始化设备选择器
 */
function initDeviceSelector() {
    const deviceSelect = document.querySelector('.device-select');
    if (!deviceSelect) return;
    
    // 加载设备列表
    axios.get('/api/devices?api=get_devices')
        .then(response => {
            // 渲染设备选项
            const devices = response.data;
            let options = '<option value="">请选择设备</option>';
            
            devices.forEach(device => {
                options += `<option value="${device.id}">${device.name} (${device.status})</option>`;
            });
            
            deviceSelect.innerHTML = options;
        })
        .catch(error => {
            console.error('加载设备列表出错:', error);
            deviceSelect.innerHTML = '<option value="">加载设备失败</option>';
        });
}

/**
 * 初始化折叠面板功能
 */
function initCollapsiblePanels() {
    // 获取所有可折叠的面板标题
    const collapsibleHeaders = document.querySelectorAll('.panel-header.collapsible');
    
    // 为每个可折叠标题添加事件监听
    collapsibleHeaders.forEach(header => {
        // 获取目标面板体
        const targetId = header.getAttribute('data-bs-target');
        const targetPanel = document.querySelector(targetId);
        const headerActions = header.querySelector('.header-actions');
        
        // 监听Bootstrap折叠事件
        if (targetPanel) {
            targetPanel.addEventListener('show.bs.collapse', function() {
                header.setAttribute('aria-expanded', 'true');
            });
            
            targetPanel.addEventListener('hide.bs.collapse', function() {
                header.setAttribute('aria-expanded', 'false');
            });
        }
    });
}

/**
 * 初始化测试用例和测试任务面板
 */
function initTestPanels() {
    // 加载测试用例列表
    loadTestcases();
    
    // 加载测试任务列表
    loadTesttasks();
    
    // 监听面板展开/折叠事件，动态加载数据
    setupPanelListeners();
}

/**
 * 设置面板展开/折叠事件监听
 */
function setupPanelListeners() {
    // 测试用例面板
    const testcasesPanel = document.getElementById('testcases-body');
    if (testcasesPanel) {
        testcasesPanel.addEventListener('show.bs.collapse', function() {
            loadTestcases();
        });
    }
    
    // 测试任务面板
    const testtasksPanel = document.getElementById('testtasks-body');
    if (testtasksPanel) {
        testtasksPanel.addEventListener('show.bs.collapse', function() {
            loadTesttasks();
        });
    }
}

/**
 * 设置添加按钮和刷新按钮的事件处理
 */
function setupPanelButtons() {
    // 测试用例添加按钮
    const addTestcaseBtn = document.querySelector('.panel-header[data-bs-target="#testcases-body"] .add-btn');
    if (addTestcaseBtn) {
        addTestcaseBtn.addEventListener('click', function(e) {
            e.stopPropagation(); // 阻止事件冒泡，避免触发折叠
            showCreateTestcaseDialog();
        });
    }
    
    // 测试用例刷新按钮
    const refreshTestcaseBtn = document.querySelector('.panel-header[data-bs-target="#testcases-body"] .refresh-btn');
    if (refreshTestcaseBtn) {
        refreshTestcaseBtn.addEventListener('click', function(e) {
            e.stopPropagation(); // 阻止事件冒泡，避免触发折叠
            loadTestcases();
        });
    }
    
    // 测试任务添加按钮
    const addTesttaskBtn = document.querySelector('.panel-header[data-bs-target="#testtasks-body"] .add-btn');
    if (addTesttaskBtn) {
        addTesttaskBtn.addEventListener('click', function(e) {
            e.stopPropagation(); // 阻止事件冒泡，避免触发折叠
            showCreateTesttaskDialog();
        });
    }
    
    // 测试任务刷新按钮
    const refreshTesttaskBtn = document.querySelector('.panel-header[data-bs-target="#testtasks-body"] .refresh-btn');
    if (refreshTesttaskBtn) {
        refreshTesttaskBtn.addEventListener('click', function(e) {
            e.stopPropagation(); // 阻止事件冒泡，避免触发折叠
            loadTesttasks();
        });
    }
}

/**
 * 加载测试用例列表
 */
function loadTestcases() {
    const testcasesList = document.getElementById('project-testcases');
    if (!testcasesList) return;
    
    // 显示加载指示器
    testcasesList.innerHTML = '<div class="loading-indicator"><i class="bi bi-arrow-repeat spin"></i> 正在加载...</div>';
    
    // 获取项目ID
    const projectId = document.querySelector('.project-path .path').getAttribute('data-id');
    
    // 发送API请求获取测试用例列表
    axios.get(`/api/projects?api=get_test_cases&id=${projectId}`)
        .then(response => {
            // 渲染测试用例列表
            renderTestcases(testcasesList, response.data);
        })
        .catch(error => {
            console.error('加载测试用例出错:', error);
            testcasesList.innerHTML = `<div class="error-message"><i class="bi bi-exclamation-triangle"></i> 加载失败: ${error.message}</div>`;
        });
}

/**
 * 渲染测试用例列表
 * @param {HTMLElement} container - 容器元素
 * @param {Array} testcases - 测试用例数据
 */
function renderTestcases(container, testcases) {
    if (!testcases || testcases.length === 0) {
        container.innerHTML = '<div class="empty-message"><i class="bi bi-info-circle"></i> 暂无测试用例</div>';
        return;
    }
    
    let html = '';
    testcases.forEach(testcase => {
        html += `
        <li class="file-item" data-id="${testcase.id}">
            <div class="file-item-content">
                <span class="file-name">${testcase.name}</span>
            </div>
        </li>`;
    });
    
    container.innerHTML = html;
    
    // 添加测试用例项的点击事件
    setupTestcaseItemEvents();
}

/**
 * 设置测试用例项的事件
 */
function setupTestcaseItemEvents() {
    // 测试用例点击事件
    const testcaseItems = document.querySelectorAll('#project-testcases .file-item');
    testcaseItems.forEach(item => {
        item.addEventListener('click', function(e) {
            if (!e.target.closest('.file-actions')) {
                // 移除其他测试用例的选中状态
                document.querySelectorAll('#project-testcases .file-item').forEach(el => {
                    el.classList.remove('active');
                });
                
                // 添加当前测试用例的选中状态
                this.classList.add('active');
                
                const testcaseId = this.getAttribute('data-id');
                loadTestcaseSteps(testcaseId);
            }
        });
        
        // 编辑按钮
        const editBtn = item.querySelector('.edit-testcase');
        if (editBtn) {
            editBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                const testcaseId = item.getAttribute('data-id');
                editTestcase(testcaseId);
            });
        }
        
        // 删除按钮
        const deleteBtn = item.querySelector('.delete-testcase');
        if (deleteBtn) {
            deleteBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                const testcaseId = item.getAttribute('data-id');
                deleteTestcase(testcaseId);
            });
        }
    });
}

/**
 * 加载测试用例的步骤数据
 * @param {string} projectId - 项目ID
 * @param {string} testcaseId - 测试用例ID
 */
function loadTestcaseSteps(projectId, testcaseId) {
    // 显示加载指示器
    const flowContainer = document.getElementById('flow-container');
    flowContainer.innerHTML = '<div class="loading-indicator"><i class="bi bi-arrow-repeat spin"></i> 正在加载测试步骤...</div>';
    
    // 发送API请求获取测试步骤数据
    axios.get(`/project/${projectId}/${testcaseId}`)
        .then(response => {
            // 渲染测试步骤
            renderTestSteps(flowContainer, response.data);
        })
        .catch(error => {
            console.error('加载测试步骤出错:', error);
            flowContainer.innerHTML = `<div class="error-message"><i class="bi bi-exclamation-triangle"></i> 加载失败: ${error.message}</div>`;
        });
}

/**
 * 渲染测试步骤到流程编辑器
 * @param {HTMLElement} container - 容器元素
 * @param {Array} steps - 测试步骤数据
 */
function renderTestSteps(container, steps) {
    if (!steps || steps.length === 0) {
        container.innerHTML = '<div class="empty-flow-message"><i class="bi bi-info-circle"></i><p>该测试用例暂无测试步骤</p></div>';
        return;
    }
    
    let html = '';
    
    steps.forEach((step, index) => {
        // 生成步骤块HTML
        html += generateStepBlockHtml(step, index);
        
        // 如果不是最后一个步骤，添加连接器
        if (index < steps.length - 1) {
            html += `
            <div class="step-connector">
                <div class="connector-line"></div>
                <button class="add-step-btn" data-bs-toggle="modal" data-bs-target="#stepSelectorModal" data-position="${index + 1}"><i class="bi bi-plus"></i></button>
            </div>`;
        }
    });
    
    // 添加最后的添加步骤按钮
    html += `
    <div class="step-connector">
        <div class="connector-line"></div>
        <button class="add-step-btn" data-bs-toggle="modal" data-bs-target="#stepSelectorModal" data-position="${steps.length}"><i class="bi bi-plus"></i></button>
    </div>`;
    
    container.innerHTML = html;
    
    // 设置步骤块的事件
    setupStepBlockEvents();
}

/**
 * 生成步骤块的HTML
 * @param {Object} step - 步骤数据
 * @param {number} index - 步骤索引
 * @returns {string} 步骤块HTML
 */
function generateStepBlockHtml(step, index) {
    // 生成参数HTML
    let paramsHtml = '';
    if (step.params) {
        Object.entries(step.params).forEach(([key, value]) => {
            paramsHtml += `
            <div class="step-param">
                <span class="param-name">${key}:</span>
                <span class="param-value">${value}</span>
            </div>`;
        });
    }
    
    // 生成步骤块HTML
    return `
    <div class="step-block" data-step-id="${step.id}" data-step-index="${index}">
        <div class="step-header">
            <span class="step-title">${step.title || step.type}</span>
            <div class="step-actions">
                <button class="btn btn-sm btn-link run-step-btn" title="执行"><i class="bi bi-play-fill"></i></button>
                <div class="dropdown">
                    <button class="btn btn-sm btn-link" data-bs-toggle="dropdown" aria-expanded="false" title="更多操作">
                        <i class="bi bi-three-dots-vertical"></i>
                    </button>
                    <ul class="dropdown-menu dropdown-menu-end">
                        <li><a class="dropdown-item edit-step-btn" href="#">编辑</a></li>
                        <li><a class="dropdown-item duplicate-step-btn" href="#">复制</a></li>
                        <li><hr class="dropdown-divider"></li>
                        <li><a class="dropdown-item text-danger delete-step-btn" href="#">删除</a></li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="step-body">
            ${paramsHtml}
            
            <!-- 可折叠的额外属性 -->
            <div class="step-additional-properties">
                <div class="property-section">
                    <div class="property-header collapsed" data-bs-toggle="collapse" data-bs-target="#properties-${index}" aria-expanded="false">
                        <span>显示额外属性</span>
                        <i class="bi bi-chevron-down"></i>
                    </div>
                </div>
                
                <div id="properties-${index}" class="collapse">
                    <!-- 时间设置 -->
                    <div class="property-section">
                        <div class="property-header" data-bs-toggle="collapse" data-bs-target="#timings-${index}" aria-expanded="true">
                            <span>时间设置</span>
                            <i class="bi bi-chevron-down"></i>
                        </div>
                        <div id="timings-${index}" class="collapse show">
                            <div class="property-content">
                                <div class="property-row">
                                    <div class="property-label">延迟前</div>
                                    <div class="property-value">
                                        <input type="text" class="form-control form-control-sm delay-before" value="${step.delayBefore || '0.2'}" data-original-value="${step.delayBefore || '0.2'}">
                                    </div>
                                </div>
                                <div class="property-row">
                                    <div class="property-label">延迟后</div>
                                    <div class="property-value">
                                        <input type="text" class="form-control form-control-sm delay-after" value="${step.delayAfter || '0.3'}" data-original-value="${step.delayAfter || '0.3'}">
                                    </div>
                                </div>
                                <div class="property-row">
                                    <div class="property-label">超时</div>
                                    <div class="property-value">
                                        <input type="text" class="form-control form-control-sm timeout" value="${step.timeout || '30'}" data-original-value="${step.timeout || '30'}">
                                    </div>
                                </div>
                                <div class="property-row">
                                    <div class="property-label">出错时继续</div>
                                    <div class="property-value radio-group">
                                        <div class="form-check form-check-inline">
                                            <input class="form-check-input continue-on-error" type="radio" name="continueOnError-${index}" id="continueTrue-${index}" value="true" ${step.continueOnError ? 'checked' : ''}>
                                            <label class="form-check-label" for="continueTrue-${index}">是</label>
                                        </div>
                                        <div class="form-check form-check-inline">
                                            <input class="form-check-input continue-on-error" type="radio" name="continueOnError-${index}" id="continueFalse-${index}" value="false" ${!step.continueOnError ? 'checked' : ''}>
                                            <label class="form-check-label" for="continueFalse-${index}">否</label>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>`;
}

/**
 * 设置步骤块的事件
 */
function setupStepBlockEvents() {
    // 编辑步骤按钮
    document.querySelectorAll('.edit-step-btn').forEach(btn => {
        btn.addEventListener('click', function(e) {
            e.preventDefault();
            const stepBlock = this.closest('.step-block');
            const stepId = stepBlock.getAttribute('data-step-id');
            editStep(stepId);
        });
    });
    
    // 删除步骤按钮
    document.querySelectorAll('.delete-step-btn').forEach(btn => {
        btn.addEventListener('click', function(e) {
            e.preventDefault();
            const stepBlock = this.closest('.step-block');
            const stepId = stepBlock.getAttribute('data-step-id');
            deleteStep(stepId);
        });
    });
    
    // 复制步骤按钮
    document.querySelectorAll('.duplicate-step-btn').forEach(btn => {
        btn.addEventListener('click', function(e) {
            e.preventDefault();
            const stepBlock = this.closest('.step-block');
            const stepId = stepBlock.getAttribute('data-step-id');
            duplicateStep(stepId);
        });
    });
    
    // 运行步骤按钮
    document.querySelectorAll('.run-step-btn').forEach(btn => {
        btn.addEventListener('click', function(e) {
            e.preventDefault();
            const stepBlock = this.closest('.step-block');
            const stepId = stepBlock.getAttribute('data-step-id');
            runStep(stepId);
        });
    });
    
    // 步骤属性输入框变化事件
    document.querySelectorAll('.step-additional-properties input').forEach(input => {
        input.addEventListener('change', function() {
            const stepBlock = this.closest('.step-block');
            const stepId = stepBlock.getAttribute('data-step-id');
            const originalValue = this.getAttribute('data-original-value');
            
            // 如果值发生变化，保存更改
            if (this.value !== originalValue) {
                saveStepPropertyChange(stepId, this);
            }
        });
    });
    
    // 添加步骤按钮
    document.querySelectorAll('.add-step-btn').forEach(btn => {
        btn.addEventListener('click', function() {
            const position = this.getAttribute('data-position');
            // 保存位置信息到模态框，以便在创建步骤时使用
            document.getElementById('stepSelectorModal').setAttribute('data-insert-position', position);
        });
    });
}

/**
 * 加载测试任务列表
 */
function loadTesttasks() {
    const testtasksList = document.getElementById('project-testtasks');
    if (!testtasksList) return;
    
    // 显示加载指示器
    testtasksList.innerHTML = '<div class="loading-indicator"><i class="bi bi-arrow-repeat spin"></i> 正在加载...</div>';
    
    // 获取项目ID
    const projectId = document.querySelector('.project-path .path').getAttribute('data-id');
    
    // 发送API请求获取测试任务列表
    axios.get(`/api/projects?api=get_test_tasks&id=${projectId}`)
        .then(response => {
            // 渲染测试任务列表
            renderTesttasks(testtasksList, response.data);
        })
        .catch(error => {
            console.error('加载测试任务出错:', error);
            testtasksList.innerHTML = `<div class="error-message"><i class="bi bi-exclamation-triangle"></i> 加载失败: ${error.message}</div>`;
        });
}

/**
 * 渲染测试任务列表
 * @param {HTMLElement} container - 容器元素
 * @param {Array} testtasks - 测试任务数据
 */
function renderTesttasks(container, testtasks) {
    if (!testtasks || testtasks.length === 0) {
        container.innerHTML = '<div class="empty-message"><i class="bi bi-info-circle"></i> 暂无测试任务</div>';
        return;
    }
    
    let html = '';
    testtasks.forEach(testtask => {
        html += `
        <li class="file-item" data-id="${testtask.id}">
            <div class="file-item-content">
                <span class="file-name">${testtask.name}</span>
            </div>
        </li>`;
    });
    
    container.innerHTML = html;
    
    // 添加测试任务项的点击事件
    setupTesttaskItemEvents();
}

/**
 * 设置测试任务项的事件
 */
function setupTesttaskItemEvents() {
    // 测试任务点击事件
    const testtaskItems = document.querySelectorAll('#project-testtasks .file-item');
    testtaskItems.forEach(item => {
        item.addEventListener('click', function(e) {
            if (!e.target.closest('.file-actions')) {
                const testtaskId = this.getAttribute('data-id');
                openTesttask(testtaskId);
            }
        });
        
        // 编辑按钮
        const editBtn = item.querySelector('.edit-testtask');
        if (editBtn) {
            editBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                const testtaskId = item.getAttribute('data-id');
                editTesttask(testtaskId);
            });
        }
        
        // 删除按钮
        const deleteBtn = item.querySelector('.delete-testtask');
        if (deleteBtn) {
            deleteBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                const testtaskId = item.getAttribute('data-id');
                deleteTesttask(testtaskId);
            });
        }
    });
}

/**
 * 编辑测试步骤
 * @param {string} stepId - 步骤ID
 */
function editStep(stepId) {
    // 获取步骤数据
    const stepBlock = document.querySelector(`.step-block[data-step-id="${stepId}"]`);
    if (!stepBlock) return;
    
    const stepTitle = stepBlock.querySelector('.step-title').textContent;
    const stepIndex = stepBlock.getAttribute('data-step-index');
    
    // 获取当前选中的测试用例ID
    const activeTestcase = document.querySelector('#project-testcases .file-item.active');
    if (!activeTestcase) return;
    const testcaseId = activeTestcase.getAttribute('data-id');
    
    // 发送API请求获取步骤详细数据
    axios.get(`/api/teststeps?api=get_step_details&id=${stepId}`)
        .then(response => {
            const stepData = response.data;
            
            // 填充编辑表单
            document.getElementById('stepId').value = stepId;
            document.getElementById('stepType').value = stepData.type;
            document.getElementById('stepTitle').value = stepData.title || stepData.type;
            
            // 根据步骤类型动态生成参数表单
            generateStepParamsForm(stepData);
            
            // 显示编辑模态框
            const modal = new bootstrap.Modal(document.getElementById('stepEditModal'));
            modal.show();
            
            // 设置保存按钮事件
            document.getElementById('saveStepBtn').onclick = function() {
                saveStepChanges(testcaseId, stepId);
            };
        })
        .catch(error => {
            console.error('获取步骤详情出错:', error);
            showNotification('error', `获取步骤详情失败: ${error.message}`);
        });
}

/**
 * 根据步骤类型生成参数表单
 * @param {Object} stepData - 步骤数据
 */
function generateStepParamsForm(stepData) {
    const container = document.getElementById('stepParamsContainer');
    container.innerHTML = '';
    
    // 根据步骤类型生成不同的表单
    switch (stepData.type) {
        case 'startApp':
            container.innerHTML = `
            <div class="mb-3">
                <label for="appPackage" class="form-label">应用包名</label>
                <input type="text" class="form-control" id="appPackage" name="appPackage" value="${stepData.params?.appPackage || ''}" required>
            </div>
            <div class="mb-3">
                <label for="waitTime" class="form-label">等待时间(秒)</label>
                <input type="number" class="form-control" id="waitTime" name="waitTime" value="${stepData.params?.waitTime || '3'}" required>
            </div>`;
            break;
            
        case 'click':
            container.innerHTML = `
            <div class="mb-3">
                <label for="elementId" class="form-label">元素ID</label>
                <input type="text" class="form-control" id="elementId" name="elementId" value="${stepData.params?.elementId || ''}" required>
            </div>
            <div class="mb-3">
                <label for="waitTime" class="form-label">等待时间(秒)</label>
                <input type="number" class="form-control" id="waitTime" name="waitTime" value="${stepData.params?.waitTime || '1'}" required>
            </div>`;
            break;
            
        case 'input':
            container.innerHTML = `
            <div class="mb-3">
                <label for="elementId" class="form-label">元素ID</label>
                <input type="text" class="form-control" id="elementId" name="elementId" value="${stepData.params?.elementId || ''}" required>
            </div>
            <div class="mb-3">
                <label for="text" class="form-label">输入文本</label>
                <input type="text" class="form-control" id="text" name="text" value="${stepData.params?.text || ''}" required>
            </div>`;
            break;
            
        case 'wait':
            container.innerHTML = `
            <div class="mb-3">
                <label for="waitTime" class="form-label">等待时间(秒)</label>
                <input type="number" class="form-control" id="waitTime" name="waitTime" value="${stepData.params?.waitTime || '3'}" required>
            </div>`;
            break;
            
        case 'assertion':
            container.innerHTML = `
            <div class="mb-3">
                <label for="elementId" class="form-label">元素ID</label>
                <input type="text" class="form-control" id="elementId" name="elementId" value="${stepData.params?.elementId || ''}" required>
            </div>
            <div class="mb-3">
                <label for="condition" class="form-label">条件</label>
                <select class="form-select" id="condition" name="condition">
                    <option value="exists" ${stepData.params?.condition === 'exists' ? 'selected' : ''}>存在</option>
                    <option value="not_exists" ${stepData.params?.condition === 'not_exists' ? 'selected' : ''}>不存在</option>
                    <option value="visible" ${stepData.params?.condition === 'visible' ? 'selected' : ''}>可见</option>
                    <option value="not_visible" ${stepData.params?.condition === 'not_visible' ? 'selected' : ''}>不可见</option>
                </select>
            </div>`;
            break;
            
        case 'custom':
            container.innerHTML = `
            <div class="mb-3">
                <label for="scriptContent" class="form-label">脚本内容</label>
                <textarea class="form-control" id="scriptContent" name="scriptContent" rows="5">${stepData.params?.scriptContent || ''}</textarea>
            </div>`;
            break;
            
        default:
            container.innerHTML = '<div class="alert alert-warning">未知的步骤类型</div>';
    }
}

/**
 * 保存步骤更改
 * @param {string} testcaseId - 测试用例ID
 * @param {string} stepId - 步骤ID
 */
function saveStepChanges(testcaseId, stepId) {
    // 获取表单数据
    const form = document.getElementById('stepEditForm');
    const formData = new FormData(form);
    const stepType = formData.get('stepType');
    const stepTitle = formData.get('stepTitle');
    
    // 构建参数对象
    const params = {};
    switch (stepType) {
        case 'startApp':
            params.appPackage = formData.get('appPackage');
            params.waitTime = formData.get('waitTime');
            break;
            
        case 'click':
            params.elementId = formData.get('elementId');
            params.waitTime = formData.get('waitTime');
            break;
            
        case 'input':
            params.elementId = formData.get('elementId');
            params.text = formData.get('text');
            break;
            
        case 'wait':
            params.waitTime = formData.get('waitTime');
            break;
            
        case 'assertion':
            params.elementId = formData.get('elementId');
            params.condition = formData.get('condition');
            break;
            
        case 'custom':
            params.scriptContent = formData.get('scriptContent');
            break;
    }
    
    // 构建步骤数据
    const stepData = {
        id: stepId,
        type: stepType,
        title: stepTitle,
        params: params
    };
    
    // 发送API请求保存步骤
    axios.post(`/api/teststeps?api=update_step`, {
        testcaseId: testcaseId,
        stepId: stepId,
        stepData: stepData
    })
    .then(response => {
        // 关闭模态框
        const modal = bootstrap.Modal.getInstance(document.getElementById('stepEditModal'));
        modal.hide();
        
        // 重新加载测试步骤
        loadTestcaseSteps(testcaseId);
        
        // 显示成功通知
        showNotification('success', '步骤保存成功');
    })
    .catch(error => {
        console.error('保存步骤出错:', error);
        showNotification('error', `保存步骤失败: ${error.message}`);
    });
}

/**
 * 保存步骤属性更改
 * @param {string} stepId - 步骤ID
 * @param {HTMLElement} inputElement - 输入元素
 */
function saveStepPropertyChange(stepId, inputElement) {
    // 获取当前选中的测试用例ID
    const activeTestcase = document.querySelector('#project-testcases .file-item.active');
    if (!activeTestcase) return;
    const testcaseId = activeTestcase.getAttribute('data-id');
    
    // 获取属性名和值
    let propertyName = '';
    let propertyValue = inputElement.value;
    
    if (inputElement.classList.contains('delay-before')) {
        propertyName = 'delayBefore';
    } else if (inputElement.classList.contains('delay-after')) {
        propertyName = 'delayAfter';
    } else if (inputElement.classList.contains('timeout')) {
        propertyName = 'timeout';
    } else if (inputElement.classList.contains('continue-on-error')) {
        propertyName = 'continueOnError';
        propertyValue = inputElement.value === 'true';
    }
    
    if (!propertyName) return;
    
    // 发送API请求保存属性更改
    axios.post(`/api/teststeps?api=update_step_property`, {
        testcaseId: testcaseId,
        stepId: stepId,
        propertyName: propertyName,
        propertyValue: propertyValue
    })
    .then(response => {
        // 更新原始值属性
        inputElement.setAttribute('data-original-value', propertyValue);
        
        // 显示成功通知
        showNotification('success', '属性更新成功');
    })
    .catch(error => {
        console.error('更新步骤属性出错:', error);
        showNotification('error', `更新属性失败: ${error.message}`);
        
        // 恢复原始值
        const originalValue = inputElement.getAttribute('data-original-value');
        inputElement.value = originalValue;
    });
}

/**
 * 删除测试步骤
 * @param {string} stepId - 步骤ID
 */
function deleteStep(stepId) {
    if (!confirm('确定要删除此步骤吗？')) return;
    
    // 获取当前选中的测试用例ID
    const activeTestcase = document.querySelector('#project-testcases .file-item.active');
    if (!activeTestcase) return;
    const testcaseId = activeTestcase.getAttribute('data-id');
    
    // 发送API请求删除步骤
    axios.post(`/api/teststeps?api=delete_step`, {
        testcaseId: testcaseId,
        stepId: stepId
    })
    .then(response => {
        // 重新加载测试步骤
        loadTestcaseSteps(testcaseId);
        
        // 显示成功通知
        showNotification('success', '步骤删除成功');
    })
    .catch(error => {
        console.error('删除步骤出错:', error);
        showNotification('error', `删除步骤失败: ${error.message}`);
    });
}

/**
 * 复制测试步骤
 * @param {string} stepId - 步骤ID
 */
function duplicateStep(stepId) {
    // 获取当前选中的测试用例ID
    const activeTestcase = document.querySelector('#project-testcases .file-item.active');
    if (!activeTestcase) return;
    const testcaseId = activeTestcase.getAttribute('data-id');
    
    // 发送API请求复制步骤
    axios.post(`/api/teststeps?api=duplicate_step`, {
        testcaseId: testcaseId,
        stepId: stepId
    })
    .then(response => {
        // 重新加载测试步骤
        loadTestcaseSteps(testcaseId);
        
        // 显示成功通知
        showNotification('success', '步骤复制成功');
    })
    .catch(error => {
        console.error('复制步骤出错:', error);
        showNotification('error', `复制步骤失败: ${error.message}`);
    });
}

/**
 * 运行单个测试步骤
 * @param {string} stepId - 步骤ID
 */
function runStep(stepId) {
    // 获取当前选中的测试用例ID
    const activeTestcase = document.querySelector('#project-testcases .file-item.active');
    if (!activeTestcase) return;
    const testcaseId = activeTestcase.getAttribute('data-id');
    
    // 获取选中的设备
    const deviceSelect = document.querySelector('.device-select');
    if (!deviceSelect || !deviceSelect.value) {
        showNotification('warning', '请先选择一个设备');
        return;
    }
    const deviceId = deviceSelect.value;
    
    // 发送API请求运行步骤
    axios.post(`/api/teststeps?api=run_step`, {
        testcaseId: testcaseId,
        stepId: stepId,
        deviceId: deviceId
    })
    .then(response => {
        // 显示成功通知
        showNotification('success', '步骤执行已开始');
    })
    .catch(error => {
        console.error('执行步骤出错:', error);
        showNotification('error', `执行步骤失败: ${error.message}`);
    });
}

/**
 * 显示通知
 * @param {string} type - 通知类型 (success, error, warning, info)
 * @param {string} message - 通知消息
 */
function showNotification(type, message) {
    const notificationContainer = document.getElementById('notification-container');
    if (!notificationContainer) {
        // 创建通知容器
        const container = document.createElement('div');
        container.id = 'notification-container';
        document.body.appendChild(container);
    }
    
    // 创建通知元素
    const notification = document.createElement('div');
    notification.className = `notification notification-${type}`;
    
    // 设置图标
    let icon = '';
    switch (type) {
        case 'success': icon = 'bi-check-circle-fill'; break;
        case 'error': icon = 'bi-x-circle-fill'; break;
        case 'warning': icon = 'bi-exclamation-triangle-fill'; break;
        case 'info': default: icon = 'bi-info-circle-fill';
    }
    
    // 设置通知内容
    notification.innerHTML = `
    <div class="notification-icon">
        <i class="bi ${icon}"></i>
    </div>
    <div class="notification-content">
        <div class="notification-message">${message}</div>
    </div>
    <button class="notification-close">
        <i class="bi bi-x"></i>
    </button>`;
    
    // 添加到容器
    document.getElementById('notification-container').appendChild(notification);
    
    // 设置关闭按钮事件
    const closeBtn = notification.querySelector('.notification-close');
    closeBtn.addEventListener('click', function() {
        notification.classList.add('notification-hiding');
        setTimeout(() => {
            notification.remove();
        }, 300);
    });
    
    // 自动关闭
    setTimeout(() => {
        if (notification.parentNode) {
            notification.classList.add('notification-hiding');
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.remove();
                }
            }, 300);
        }
    }, 5000);
}

/**
 * 显示创建测试用例对话框
 */
function showCreateTestcaseDialog() {
    // 创建对话框HTML
    const dialogHTML = `
    <div class="modal fade" id="createTestcaseModal" tabindex="-1" aria-labelledby="createTestcaseModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="createTestcaseModalLabel">新建测试用例</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
                </div>
                <div class="modal-body">
                    <form id="createTestcaseForm">
                        <div class="mb-3">
                            <label for="testcaseName" class="form-label">测试用例名称</label>
                            <input type="text" class="form-control" id="testcaseName" required>
                        </div>
                        <div class="mb-3">
                            <label for="testcaseDescription" class="form-label">描述</label>
                            <textarea class="form-control" id="testcaseDescription" rows="3"></textarea>
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-primary" id="createTestcaseBtn">创建</button>
                </div>
            </div>
        </div>
    </div>`;
    
    // 添加对话框到DOM
    document.body.insertAdjacentHTML('beforeend', dialogHTML);
    
    // 获取对话框元素
    const modalEl = document.getElementById('createTestcaseModal');
    const modal = new bootstrap.Modal(modalEl);
    
    // 显示对话框
    modal.show();
    
    // 绑定创建按钮事件
    const createBtn = document.getElementById('createTestcaseBtn');
    createBtn.addEventListener('click', function() {
        createTestcase();
    });
    
    // 对话框关闭后移除
    modalEl.addEventListener('hidden.bs.modal', function() {
        modalEl.remove();
    });
}

/**
 * 创建测试用例
 */
function createTestcase() {
    // 获取表单数据
    const name = document.getElementById('testcaseName').value.trim();
    const description = document.getElementById('testcaseDescription').value.trim();
    
    if (!name) {
        alert('请输入测试用例名称');
        return;
    }
    
    // 获取项目ID
    const projectId = document.querySelector('.project-path .path').getAttribute('data-id');
    
    // 创建测试用例数据
    const testcaseData = {
        name: name,
        description: description,
        project_id: projectId
    };
    
    // 发送API请求创建测试用例
    fetch(`/api/projects/${projectId}/testcases`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(testcaseData)
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('创建测试用例失败');
        }
        return response.json();
    })
    .then(data => {
        // 关闭对话框
        const modal = bootstrap.Modal.getInstance(document.getElementById('createTestcaseModal'));
        modal.hide();
        
        // 重新加载测试用例列表
        loadTestcases();
        
        // 显示成功消息
        showNotification('success', '测试用例创建成功');
    })
    .catch(error => {
        console.error('创建测试用例出错:', error);
        showNotification('error', `创建失败: ${error.message}`);
    });
}

/**
 * 显示创建测试任务对话框
 */
function showCreateTesttaskDialog() {
    // 创建对话框HTML
    const dialogHTML = `
    <div class="modal fade" id="createTesttaskModal" tabindex="-1" aria-labelledby="createTesttaskModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="createTesttaskModalLabel">新建测试任务</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
                </div>
                <div class="modal-body">
                    <form id="createTesttaskForm">
                        <div class="mb-3">
                            <label for="testtaskName" class="form-label">测试任务名称</label>
                            <input type="text" class="form-control" id="testtaskName" required>
                        </div>
                        <div class="mb-3">
                            <label for="testtaskDescription" class="form-label">描述</label>
                            <textarea class="form-control" id="testtaskDescription" rows="3"></textarea>
                        </div>
                        <div class="mb-3">
                            <label for="testtaskDevice" class="form-label">目标设备</label>
                            <select class="form-select" id="testtaskDevice">
                                <option value="" selected>选择设备...</option>
                                <!-- 设备列表将通过API动态加载 -->
                            </select>
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-primary" id="createTesttaskBtn">创建</button>
                </div>
            </div>
        </div>
    </div>`;
    
    // 添加对话框到DOM
    document.body.insertAdjacentHTML('beforeend', dialogHTML);
    
    // 获取对话框元素
    const modalEl = document.getElementById('createTesttaskModal');
    const modal = new bootstrap.Modal(modalEl);
    
    // 加载设备列表
    loadDeviceOptions();
    
    // 显示对话框
    modal.show();
    
    // 绑定创建按钮事件
    const createBtn = document.getElementById('createTesttaskBtn');
    createBtn.addEventListener('click', function() {
        createTesttask();
    });
    
    // 对话框关闭后移除
    modalEl.addEventListener('hidden.bs.modal', function() {
        modalEl.remove();
    });
}

/**
 * 加载设备选项
 */
function loadDeviceOptions() {
    const deviceSelect = document.getElementById('testtaskDevice');
    if (!deviceSelect) return;
    
    // 发送API请求获取设备列表
    fetch('/api/devices')
        .then(response => {
            if (!response.ok) {
                throw new Error('获取设备列表失败');
            }
            return response.json();
        })
        .then(data => {
            // 添加设备选项
            data.forEach(device => {
                const option = document.createElement('option');
                option.value = device.id;
                option.textContent = device.name;
                deviceSelect.appendChild(option);
            });
        })
        .catch(error => {
            console.error('加载设备列表出错:', error);
            deviceSelect.innerHTML = '<option value="" selected>加载设备失败</option>';
        });
}

/**
 * 创建测试任务
 */
function createTesttask() {
    // 获取表单数据
    const name = document.getElementById('testtaskName').value.trim();
    const description = document.getElementById('testtaskDescription').value.trim();
    const deviceId = document.getElementById('testtaskDevice').value;
    
    if (!name) {
        alert('请输入测试任务名称');
        return;
    }
    
    // 获取项目ID
    const projectId = document.querySelector('.project-path .path').getAttribute('data-id');
    
    // 创建测试任务数据
    const testtaskData = {
        name: name,
        description: description,
        project_id: projectId,
        device_id: deviceId || null
    };
    
    // 发送API请求创建测试任务
    fetch(`/api/projects/${projectId}/testtasks`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(testtaskData)
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('创建测试任务失败');
        }
        return response.json();
    })
    .then(data => {
        // 关闭对话框
        const modal = bootstrap.Modal.getInstance(document.getElementById('createTesttaskModal'));
        modal.hide();
        
        // 重新加载测试任务列表
        loadTesttasks();
        
        // 显示成功消息
        showNotification('success', '测试任务创建成功');
    })
    .catch(error => {
        console.error('创建测试任务出错:', error);
        showNotification('error', `创建失败: ${error.message}`);
    });
}

/**
 * 打开测试用例
 * @param {string} testcaseId - 测试用例ID
 */
function openTestcase(testcaseId) {
    console.log('打开测试用例:', testcaseId);
    // TODO: 实现打开测试用例的功能
    // 可以通过AJAX加载测试用例详情，然后在流程编辑器中显示
}

/**
 * 编辑测试用例
 * @param {string} testcaseId - 测试用例ID
 */
function editTestcase(testcaseId) {
    console.log('编辑测试用例:', testcaseId);
    // TODO: 实现编辑测试用例的功能
    // 可以弹出编辑对话框，加载测试用例详情并允许修改
}

/**
 * 删除测试用例
 * @param {string} testcaseId - 测试用例ID
 */
function deleteTestcase(testcaseId) {
    if (!confirm('确定要删除这个测试用例吗？此操作不可恢复。')) {
        return;
    }
    
    // 获取项目ID
    const projectId = document.querySelector('.project-path .path').getAttribute('data-id');
    
    // 发送API请求删除测试用例
    fetch(`/api/projects/${projectId}/testcases/${testcaseId}`, {
        method: 'DELETE'
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('删除测试用例失败');
        }
        return response.json();
    })
    .then(data => {
        // 重新加载测试用例列表
        loadTestcases();
        
        // 显示成功消息
        showNotification('success', '测试用例已删除');
    })
    .catch(error => {
        console.error('删除测试用例出错:', error);
        showNotification('error', `删除失败: ${error.message}`);
    });
}

/**
 * 打开测试任务
 * @param {string} testtaskId - 测试任务ID
 */
function openTesttask(testtaskId) {
    console.log('打开测试任务:', testtaskId);
    // TODO: 实现打开测试任务的功能
    // 可以通过AJAX加载测试任务详情，然后在流程编辑器中显示
}

/**
 * 编辑测试任务
 * @param {string} testtaskId - 测试任务ID
 */
function editTesttask(testtaskId) {
    console.log('编辑测试任务:', testtaskId);
    // TODO: 实现编辑测试任务的功能
    // 可以弹出编辑对话框，加载测试任务详情并允许修改
}

/**
 * 删除测试任务
 * @param {string} testtaskId - 测试任务ID
 */
function deleteTesttask(testtaskId) {
    if (!confirm('确定要删除这个测试任务吗？此操作不可恢复。')) {
        return;
    }
    
    // 获取项目ID
    const projectId = document.querySelector('.project-path .path').getAttribute('data-id');
    
    // 发送API请求删除测试任务
    fetch(`/api/projects/${projectId}/testtasks/${testtaskId}`, {
        method: 'DELETE'
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('删除测试任务失败');
        }
        return response.json();
    })
    .then(data => {
        // 重新加载测试任务列表
        loadTesttasks();
        
        // 显示成功消息
        showNotification('success', '测试任务已删除');
    })
    .catch(error => {
        console.error('删除测试任务出错:', error);
        showNotification('error', `删除失败: ${error.message}`);
    });
}

/**
 * 显示通知消息
 * @param {string} type - 通知类型 (success, error, warning, info)
 * @param {string} message - 通知消息
 */
function showNotification(type, message) {
    // 创建通知元素
    const notification = document.createElement('div');
    notification.className = `notification ${type}`;
    
    // 设置图标
    let icon = '';
    switch (type) {
        case 'success':
            icon = '<i class="bi bi-check-circle"></i>';
            break;
        case 'error':
            icon = '<i class="bi bi-exclamation-circle"></i>';
            break;
        case 'warning':
            icon = '<i class="bi bi-exclamation-triangle"></i>';
            break;
        case 'info':
        default:
            icon = '<i class="bi bi-info-circle"></i>';
            break;
    }
    
    // 设置通知内容
    notification.innerHTML = `
        <div class="notification-icon">${icon}</div>
        <div class="notification-content">${message}</div>
        <button class="notification-close"><i class="bi bi-x"></i></button>
    `;
    
    // 添加到文档
    document.body.appendChild(notification);
    
    // 添加关闭按钮事件
    const closeBtn = notification.querySelector('.notification-close');
    if (closeBtn) {
        closeBtn.addEventListener('click', function() {
            notification.classList.add('notification-hide');
            setTimeout(() => {
                notification.remove();
            }, 300);
        });
    }
    
    // 自动关闭
    setTimeout(() => {
        notification.classList.add('notification-hide');
        setTimeout(() => {
            notification.remove();
        }, 300);
    }, 5000);
}